﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Aludra.Core.Models
{
    public class DeckZone
    {
        private List<ICard> _deck;

        #region IField Members
        public FieldType FieldType
        {
            get { return FieldType.DeckZone; }
        }

        /// <summary>
        /// In deck zone, the Size property indicates the original size of the deck
        /// </summary>
        public int Size
        {
            get;
            private set;
        }

        public int Count
        {
            get { return _deck.Count; }
        }

        public ICard this[int index]
        {
            get
            {
                return _deck[index];
            }
        }

        public event EventHandler<CardsRemovedEventArgs> CardsRemoved;

        public event EventHandler<CardsAddedEventArgs> CardsAdded;

        #endregion

        public DeckZone(IEnumerable<ICard> deck)
        {
            _deck = new List<ICard>(deck);
            this.Size = _deck.Count;
        }
		
		public List<ICard> GetRange(int index, int count)
		{
			return _deck.GetRange(index, Count);
		}

        public void Remove(ICard item)
        {
            if (_deck.Remove(item))
            {
                // Copy to a temporary variable to be thread-safe.
                EventHandler<CardsRemovedEventArgs> temp = CardsRemoved;
                if (temp != null)
                {
                    temp(this, new CardsRemovedEventArgs(this.FieldType, new[] { item }));
                }
            }
        }

        public void RemoveRange(int index, int count)
        {
            // Copy to a temporary variable to be thread-safe.
            EventHandler<CardsRemovedEventArgs> temp = CardsRemoved;
            if (temp != null)
            {
                temp(this, new CardsRemovedEventArgs(this.FieldType, _deck.GetRange(index, count)));
            }

            _deck.RemoveRange(index, count);
        }

        public void Add(ICard item)
        {
            EventHandler<CardsAddedEventArgs> tempAdded = this.CardsAdded;
            if (tempAdded != null)
            {
                tempAdded(this, new CardsAddedEventArgs(this.FieldType, new[] { item }));
            }

            _deck.Add(item);
        }

        public void Insert(int index, ICard item)
        {
            EventHandler<CardsAddedEventArgs> tempAdded = this.CardsAdded;
            if (tempAdded != null)
            {
                tempAdded(this, new CardsAddedEventArgs(this.FieldType, new[] { item }));
            }

            _deck.Insert(index, item);
        }

        public void Clear()
        {
            // Copy to a temporary variable to be thread-safe.
            EventHandler<CardsRemovedEventArgs> temp = CardsRemoved;
            if (temp != null)
            {
                temp(this, new CardsRemovedEventArgs(this.FieldType, _deck));
            }
            _deck.Clear();
        }

        public bool Contains(ICard item)
        {
            return _deck.Contains(item);
        }

        public void Shuffle()
        {
            var rand = new Random();
            int shuffleTimes = rand.Next(_deck.Count / 2, _deck.Count), count = _deck.Count;
            for (int i = 0; i < shuffleTimes; i++)
            {
                int swapIndex1 = rand.Next(count), swapIndex2 = rand.Next(count);
                if (swapIndex1 == swapIndex2) continue;
                ICard temp = _deck[swapIndex1];
                _deck[swapIndex1] = _deck[swapIndex2];
                _deck[swapIndex2] = temp;
            }
        }
    }
}
